/*
 * L9Util.h
 *
 *  Created on: 2011-10-18
 *      Author: baixp
 */

#ifndef L9UTIL_H_
#define L9UTIL_H_
#include <FBase.h>
#include <FText.h>
using namespace Osp::Base;
using namespace Osp::Base::Utility;
using namespace Osp::Text;
#include <vector>
#include <fstream>
#include "L9InputStream.h"
#include "L9OutputStream.h"
using namespace std;
namespace lib9bada {
struct pByte {
private:
	void _init(byte* p, int off, int size) {
		if (p != null && size > 0) {
			this->size = size;
			pChar = new byte[size];
			memcpy(pChar, p + off, size);
		}
	}
	void free() {
		if (pChar != null) {
			delete[] pChar;
			pChar = null;
		}
		size = 0;
	}
public:
	byte* pChar;
	int size;

	pByte() {
		pChar = null;
		size = 0;
	}
	pByte(byte* p, int off, int size) {
		_init(p, off, size);
	}
	pByte(const pByte& bin) {
		_init(bin.pChar, 0, bin.size);
	}
	pByte& operator=(const pByte& bin) {
		if (this != &bin) {//排除自赋值的情况
			_init(bin.pChar, 0, bin.size);
		}
		return *this;
	}
	~pByte() {
		free();
	}
	void init(byte* p, int off, int size) {
		free();
		_init(p, off, size);
	}
};
class L9Util {
private:
	/////////////////////////////////压缩算法//////////////////////////////////////
	/**
	 * 设置压缩算法的头标记,bUse_Flag_Head为true这个函数才有意义
	 * @param flag byte[]
	 * @param Num int
	 */
	/*static*/
	void Set_Flag(byte* flag, int Num, bool bLz77HeadFlag) {
		if (bLz77HeadFlag) { //为真标记才有意义
			int index = Num / 8;
			int pos = Num - index * 8;
			flag[index] |= 1 << pos;
		}
	}

	/**
	 * 取得压缩算法的头标记,bUse_Flag_Head为true这个函数才有意义
	 * @param flag byte[]
	 * @param Num int
	 * @return boolean
	 */
	/*static*/
	bool Get_Flag(byte* flag, int Num, bool bLz77HeadFlag) {
		if (bLz77HeadFlag) { //为真标记才有意义
			int index = Num / 8;
			int pos = Num - index * 8;
			return (flag[index] & (1 << pos)) != 0;
		}
		return false;
	}

	//压缩数据存储结构 Flag+Data
	//Flag标记数据是原数据还是三元组数据,Data为原数据或者三元组数据
	/**
	 * LZ77压缩算法的滑动窗口字节变量
	 */
	/*static*/
	byte* _pWin;
	/**
	 * 滑动窗口的大小，由于程序中用一个字节来表示的偏移量和长度 ,所以窗口长度不能大于255
	 */
	/*static*/
	int _pWinLen; //注意由于程序中用一个字节来表示的偏移量和长度 ,所以窗口长度不能大于255

	/*static*/
	byte* _pTmpBuf;

	/*static*/
	int _lz77_off;
	/*static*/
	int _lz77_len;
	/**
	 * 使用LZ77压缩前应该先初始化滑动窗口,由于程序中用一个字节来表示的偏移量和长度 ,所以窗口长度不能大于255
	 * @param pByte byte[]
	 * @param off int
	 * @param wLen int
	 */
	/*static*/
	void LZ77_Init_Win(byte* pByte, int off, int wLen) {
		_pWinLen = wLen;
		_pWin = new byte[_pWinLen];
		_pTmpBuf = new byte[_pWinLen];
		for (int i = 0; i < _pWinLen; i++) {
			_pWin[i] = pByte[i + off];
		}
		_lz77_off = 0;
		_lz77_len = 0;
	}

	/**
	 * 清除LZ77滑动窗口所占的内存数据,java中不用，因为有垃圾收集机制
	 */
	/*static*/
	void LZ77_CleanUp_Win() {
		if (_pWin != NULL) {
			delete[] _pWin;
		}
		_pWin = NULL;

		if (_pTmpBuf != NULL) {
			delete[] _pTmpBuf;
		}
		_pTmpBuf = NULL;
	}

	/**
	 * 在滑动窗口中寻找sLen长度s的位置
	 * @param s byte[]
	 * @param sLen int
	 * @return int
	 */
	/*static*/
	int LZ77_AnsiPos(byte* s, int sLen) {
		for (int i = 0; i < _pWinLen - sLen + 1; i++) {
			int j = 0;
			for (; j < sLen; j++) {
				if (_pWin[i + j] != s[j]) {
					break;
				}
			}
			if (j == sLen) {
				return i;
			}
		}
		return -1;
	}

	/**
	 * 在滑动窗口中寻求最长匹配，返回匹配字符串在窗口中的偏移量和匹配字符串长度(_lz77_off和_lz77_len)
	 * pByte为需压缩数据,pByteLen为压缩数据的长度,pByteOff为当前偏移量 也就是说只在pByteOff至pByteLen中查找匹配
	 * @param pByte byte[]
	 * @param pByteLen int
	 * @param pByteOff int
	 * @return boolean
	 */
	/*static*/
	bool LZ77_Find_Max_Str(byte* pByte, int pByteLen, int pByteOff) {
		bool bFind = false;
		_lz77_off = 0;
		_lz77_len = 0;
		for (int i = 0; i < _pWinLen && i < pByteLen - pByteOff; i++) {
			_pTmpBuf[i] = pByte[pByteOff + i];
			int index = LZ77_AnsiPos(_pTmpBuf, i + 1);
			if (index == -1) {
				if (i == 0) {
					return false;
				}
				return true;
			}
			_lz77_off = index;
			_lz77_len = i + 1;
			bFind = true;
		}
		return bFind;
	}

	/**
	 * 移动滑动窗口 c为压缩数据的下一个字节
	 * @param c byte
	 */
	/*static*/
	void LZ77_Move_Scroll_Window(byte c) {
		//byte[] pWin = new byte[_lz77_len];
		for (int i = 0; i < _lz77_len; i++) {
			_pTmpBuf[i] = _pWin[_lz77_off + i];
		}

		if (_lz77_len == _pWinLen - 1 || _lz77_len == _pWinLen) {
			for (int i = 1; i < _lz77_len; i++) {
				_pWin[i - 1] = _pTmpBuf[i];
			}
		} else {
			for (int i = _lz77_len + 1; i < _pWinLen; i++) {
				_pWin[i - (_lz77_len + 1)] = _pWin[i];
			}

			for (int i = 0; i < _lz77_len; i++) {
				_pWin[_pWinLen - (_lz77_len + 1) + i] = _pTmpBuf[i];
			}
		}
		_pWin[_pWinLen - 1] = c;

	}

public:
	L9Util();
	virtual ~L9Util();

	static void System_arraycopy(const byte*src, int src_off, byte*dest,
			int dest_off, int len) {
		for (int i = 0; i < len; i++) {
			dest[dest_off + i] = src[src_off + i];
		}
	}

	/**
	 * 在[lower,upper)之间随机取一个值
	 * @param lower int
	 * @param upper int
	 * @return int
	 */
	static int getRandValue(int lower, int upper) {
		int value = Math::Rand() % upper;
		while (value < lower || value >= upper) {
			value = Math::Rand();
		}
		return value;
	}
	/**
	 * 在[lower,upper)之间随机取一个值,要求不能是val
	 * @param val int
	 * @param lower int
	 * @param upper int
	 * @return int
	 */
	static int getDiffRandValue(int val, int lower, int upper) {
		int tmp = -1;
		while (true) {
			tmp = getRandValue(lower, upper);
			if (val != tmp) {
				break;
			}
		}
		return tmp;
	}
	/**
	 * 在[lower,upper)之间随机取一个值,要求不能是arr中的任何一个
	 * @param arr int[]
	 * @param lower int
	 * @param upper int
	 * @return int
	 */
	static int getDiffArrRandValue(int* arr, int len, int lower, int upper) {
		int tmp = -1, i;
		while (true) {
			tmp = getRandValue(lower, upper);
			for (i = 0; i < len; i++) {
				if (tmp == arr[i]) {
					break;
				}
			}
			if (i == len) {
				break;
			}
		}
		return tmp;
	}
	/**
	 * 返回size大小且不重复的整数数组
	 * @param size int
	 * @param lower int
	 * @param upper int
	 * @return int[]
	 */
	static int* getDiffArray(int size, int lower, int upper) {
		if (size < upper - lower) {
			return NULL;
		}
		int*pArr = new int[size];
		//这里设置为[lower,upper)以外的值
		for (int i = 0; i < size; i++) {
			pArr[i] = lower - 1;
		}
		for (int i = 0; i < size; i++) {
			pArr[i] = getDiffArrRandValue(pArr, size, lower, upper);
		}
		return pArr;
	}

	/////////////////c++或c#中流 先读或写低字节 java却正好相反，先读或写高字节/////////////////

	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	/**
	 * 返回Short数字的字节数组，顺序由低到高，占2位
	 * @param i int
	 * @return byte[]
	 */
	static byte* getShortBytes(short i) {
		byte* head = new byte[2];
		L9OutputStream::writeShortLow(head, 0, i);
		return head;
	}

	/**
	 * 返回整形数字的字节数组，顺序由低到高
	 * @param i int
	 * @return byte[]
	 */
	static byte* getIntBytes(int i) {
		byte* head = new byte[4];
		L9OutputStream::writeIntLow(head, 0, i);
		return head;
	}

	/**
	 * 返回整形数字的字节数组，顺序由低到高
	 * @param i int
	 * @return byte[]
	 */
	static byte* getLongBytes(long i) {
		byte* head = new byte[8];
		L9OutputStream::writeLongLow(head, 0, i);
		return head;
	}

	/**
	 * 返回字符串的由Encode指定编码的字节数组
	 * @param Str String
	 * @param Encode String
	 * @return byte[]
	 */
	static byte* getStringBytes(string Str, string Encode) {
		/*
		 byte[] rs = null;
		 try {
		 rs = Str.getBytes(Encode);
		 } catch (UnsupportedEncodingException ex) {
		 }
		 return rs;
		 */
		//等后面来实现
		return NULL;
	}

	/**
	 * 返回字符串的由Encode指定编码的字节数组,前面带有长度,占4个字节
	 * @param Str String
	 * @param Encode String
	 * @return byte[]
	 */
	static byte* getStringBytesWithLen(string Str, string Encode) {
		/*
		 byte[] tmp = getStringBytes(Str, Encode);
		 byte[] rs = new byte[4 + tmp.length];
		 L9OutputStream.writeIntLow(rs, 0, tmp.length);
		 System_arraycopy(tmp, 0, rs, 4, tmp.length);
		 return rs;
		 */
		//等后面来实现
		return NULL;
	}

	/**
	 * Lz77压缩算法，pByte为要压缩的数据，从要压缩的数据pByte中从偏移量wOff开始取wLen个字符作为滑动窗口数据，头部标记为true 进行压缩,wLen长度不能大于255
	 * @param pByte byte[]
	 * @param wOff int
	 * @param wLen int
	 * @return byte[]
	 */
	/*static*/
	byte* LZ77_Encode(byte* pByte, int pByteLen, int wOff, int wLen) {
		return LZ77_Encode(pByte, pByteLen, pByte, wOff, wLen, true);
	}

	/**
	 * Lz77压缩算法，pByte为要压缩的数据，从要压缩的数据pByte中取前255个字符作为滑动窗口数据，头部标记为true 进行压缩
	 * 如果数据长度小于255则不压缩直接返回原数据
	 * @param pByte byte[]
	 * @return byte[]
	 */
	/*static*/
	byte* LZ77_Encode(byte* pByte, int pByteLen) {
		if (pByte == NULL || pByteLen < 255) {
			return pByte;
		}
		return LZ77_Encode(pByte, pByteLen, pByte, 0, 255, true);
	}

	/**
	 * Lz77压缩算法，pByte为要压缩的数据，pWin，wOff，wLen表示在pWin数据中从wOff偏移量中取出wLen长度的数据作为滑动窗口数据，bLz77HeadFlag表示是否使用头部标记的压缩方法
	 * @param pByte byte[]
	 * @param pWin byte[]
	 * @param wOff int
	 * @param wLen int
	 * @param bLz77HeadFlag boolean
	 * @return byte[]
	 */
	/*static*/
	byte* LZ77_Encode(byte* pByte, int pByteLen, byte* pWin, int wOff,
			int wLen, bool bLz77HeadFlag) {
		LZ77_Init_Win(pWin, wOff, wLen); //初始化

		//int pByteLen = pByte.length;
		//        byte[] pRs = new byte[pByteLen * 3 / 4]; //初始话预计压缩后大小为原大小的75%
		L9OutputStream l9Out/* = new L9OutputStream()*/;

		byte* nMaxByteFlag = NULL;
		//////////注意 大部分的JVM可能会默认初始化,但可能有少数不默认初始化的JVM就会出问题，所以在此初始化////////
		if (bLz77HeadFlag) {
			nMaxByteFlag = new byte[pByteLen / 8 + 1];
			for (int i = 0; i < pByteLen / 8 + 1; i++) {
				nMaxByteFlag[i] = 0;
			}
		}
		/////////////////////////////////////////////////////////////////////////////////////////////
		int iCount = 0;
		//        int iRs = 0;
		//        if (!bLz77HeadFlag) {
		//            //pRs[iRs++] = 0; //头部标记
		//            l9Out.writeBoolean(false);
		//        }
		for (int i = 0; i < pByteLen;) {
			//防止pRs数据越界,一般情况下是压缩会减少大小，所以在调用LZ77_Encode方法时就不需要传递最大保险值，这样就可以减少内存的使用
			//int max_rs_len = 3 * w * h + 4 + 1; //压缩的最坏结果
			//            if (iRs + 4 > pRs.length) { //三元组只需加3
			//                byte[] tmp_byte = pRs;
			//                pRs = new byte[tmp_byte.length + 1024];
			//                System_arraycopy(tmp_byte, 0, pRs, 0, tmp_byte.length);
			//            }
			//////////////////////////////////////////////////////////////////////////

			bool bFind = LZ77_Find_Max_Str(pByte, pByteLen, i);
			if (bLz77HeadFlag) { //要求最低匹配大于3，不然将不会有压缩
				if (bFind) {
					if (_lz77_len <= 3) {
						bFind = false;
						_lz77_off = 0;
						_lz77_len = 0;
					}
				}
			}
			//System.out.println(bFind+","+lz77_off+","+lz77_len);
			if (bFind) {
				iCount++;
				if (_lz77_len == pByteLen - i) { //结束
					//pRs[iRs++] = (byte) _lz77_off;
					//pRs[iRs++] = (byte) _lz77_len;
					l9Out.writeByte((byte) _lz77_off);
					l9Out.writeByte((byte) _lz77_len);

					//pRs[iRs++] = '\0';
					break;
				} else {
					//输出off,len,c
					byte c = pByte[i + _lz77_len];
					//                    pRs[iRs++] = (byte) _lz77_off;
					//                    pRs[iRs++] = (byte) _lz77_len;
					//                    pRs[iRs++] = c;
					l9Out.writeByte((byte) _lz77_off);
					l9Out.writeByte((byte) _lz77_len);
					l9Out.writeByte(c);
					//改变滑动窗口
					LZ77_Move_Scroll_Window(c);
				}
				i = i + _lz77_len + 1;
				//System.out.println("_lz77_len=" + _lz77_len);
			} else {
				//输出off,len,c
				_lz77_off = 0;
				_lz77_len = 0;
				Set_Flag(nMaxByteFlag, iCount++, bLz77HeadFlag);
				byte c = pByte[i + _lz77_len];
				if (!bLz77HeadFlag) { //要求最低匹配大于3，不然将不会有压缩
					//                    pRs[iRs++] = (byte) _lz77_off;
					//                    pRs[iRs++] = (byte) _lz77_len;
					l9Out.writeByte((byte) _lz77_off);
					l9Out.writeByte((byte) _lz77_len);
				}
				//                pRs[iRs++] = c;
				l9Out.writeByte(c);
				//改变滑动窗口
				LZ77_Move_Scroll_Window(c);
				i = i + 1;
			}
		}
		if (!bLz77HeadFlag) {
			//            System_arraycopy(pRs, 0, pRs, 0, iRs);
			//            return pRs;
		}
		//要求最低匹配大于3，不然将不会有压缩
		int nByteFlag = (iCount - 1) / 8 + 1;
		//        int nRsSize = 1 + wLen + 1 + 4 + nByteFlag + iRs; //窗口数据大小+窗口数据+头部标记+头部标记大小+头部标记数据+压缩后的数据
		//        byte[] rs_data = new byte[nRsSize];
		//
		//        int _data_offset = 0;
		//
		//        rs_data[_data_offset++] = (byte) wLen;
		//        System_arraycopy(pWin, wOff, rs_data, _data_offset, wLen);
		//        _data_offset += wLen;
		//
		//        rs_data[_data_offset++] = bLz77HeadFlag ? (byte) 1 : (byte) 0; //头部标记
		//
		//        if (bLz77HeadFlag) { //如果存在头部标记
		//            L9OutputStream.writeIntLow(rs_data, _data_offset, nByteFlag);
		//            _data_offset += 4;
		//            System_arraycopy(nMaxByteFlag, 0, rs_data, _data_offset, nByteFlag);
		//            _data_offset += nByteFlag;
		//        }
		//
		//        System_arraycopy(pRs, 0, rs_data, _data_offset, iRs);
		//        _data_offset += iRs;

		L9OutputStream out/* = new L9OutputStream()*/;
		out.writeByte((byte) wLen); //窗口数据大小
		out.writeBytes(pWin, wOff, wLen); //窗口数据
		out.writeBoolean(bLz77HeadFlag); //头部标记
		if (bLz77HeadFlag) { //头部标记数据
			out.writeInt(nByteFlag);
			out.writeBytes(nMaxByteFlag, 0, nByteFlag);
		}
		//压缩后的数据
		int len = 0;
		byte* bin = l9Out.getBytesN();
		out.writeBytes(bin, 0, l9Out.getOff());
		delete[] bin;
		bin = NULL;
		return out.getBytesN();
	}

	/**
	 * LZ77解压算法,实际要解压的数据位从offset偏移开始的pByteLen个字节数据
	 * @param pByte byte[]
	 * @param offset int
	 * @param pByteLen int
	 * @return byte[]
	 */
	/*static*/
	byte* LZ77_Decode(byte* pByte, int offset, int pByteLen, int& size) {

		L9OutputStream out/* = new L9OutputStream()*/;

		int _data_offset = offset;

		int wLen = pByte[_data_offset++] & 0xFF;
		LZ77_Init_Win(pByte, _data_offset, wLen); //初始化
		_data_offset += wLen;

		bool bLz77HeadFlag = (pByte[_data_offset++] == 1); //判断是否使用头部标记

		byte* flag = NULL;
		if (bLz77HeadFlag) { //要求最低匹配大于3，不然将不会有压缩
			int nByteFlag = L9InputStream::readIntLow(pByte, _data_offset);
			_data_offset += 4;

			flag = new byte[nByteFlag];
			System_arraycopy(pByte, _data_offset, flag, 0, nByteFlag);
			_data_offset += nByteFlag;
		}
		int iCount = 0;
		int iRs = 0;
		while (_data_offset < offset + pByteLen) {
			//			try {
			bool bFind = Get_Flag(flag, iCount++, bLz77HeadFlag);
			if (bFind) {
				byte c = pByte[_data_offset++];
				//pRs[iRs++] = c; //输出
				out.writeByte(c);
				if (_data_offset >= offset + pByteLen) { //已经解压完毕
					break;
				}
				//改变滑动窗口
				_lz77_off = 0;
				_lz77_len = 0;
				LZ77_Move_Scroll_Window(c);
			} else {
				//从窗口中取原来的数据
				_lz77_off = pByte[_data_offset++] & 0xFF;
				_lz77_len = pByte[_data_offset++] & 0xFF;

				//System.out.println(""+_lz77_off+","+_lz77_len);

				for (int i = 0; i < _lz77_len; i++) {
					byte ch = _pWin[_lz77_off + i];
					//pRs[iRs++] = ch;
					out.writeByte(ch);
				}
				if (_data_offset >= offset + pByteLen) { //已经解压完毕
					break;
				}

				byte c = pByte[_data_offset++];
				//pRs[iRs++] = c;
				out.writeByte(c);

				if (_data_offset >= offset + pByteLen) { //已经解压完毕
					break;
				}
				//改变滑动窗口
				LZ77_Move_Scroll_Window(c);
			}
			//			} catch (Exception e) {
			//				e.printStackTrace();
			//			}
		}
		size = out.getOff();
		return out.getBytesN();
	}

	/**
	 * RLE压缩算法,考虑到大部分相同的颜色都不会超过255,所以不再设立 头部标识，全部采用(color,index),color和index均为字节
	 * @param pByte byte[]
	 * @return byte[]
	 */
	/*static*/
	byte* RLE_Encode(byte* pByte, int pByteLen) {
		byte last_byte = pByte[0]; //第一个index;
		int iCount = 0;
		int iOff = 0;

		int pRsLen = pByteLen * 3 / 4;
		byte* pRs = new byte[pRsLen]; //压缩后大小预先保留原数据大小的75%

		for (int i = 0; i < pByteLen; i++) {
			if (pByte[i] == last_byte && iCount < 255) {
				iCount++;
			} else {
				if (iOff > pRsLen - 3) {
					pRs = addBytes(pRs, pRsLen, 1024);
					pRsLen = pRsLen + 1024;
				}
				pRs[iOff++] = last_byte;
				pRs[iOff++] = (byte) iCount;

				last_byte = pByte[i];
				iCount = 1;
			}
		}
		if (iOff > pRsLen - 3) {
			pRs = addBytes(pRs, pRsLen, iOff - pRsLen + 3);
			pRsLen = pRsLen + iOff - pRsLen + 3;
		}
		//输出最后一次
		pRs[iOff++] = last_byte;
		pRs[iOff++] = (byte) iCount;

		pRs = trimBytes(pRs, pRsLen, 0, iOff);

		return pRs;
	}

	/**
	 * pByte为解压缩的数据 iRsSize为为压缩前数据的大小
	 * @param pByte byte[]
	 * @param iRsSize int
	 * @return byte[]
	 */
	/*static*/
	byte* RLE_Decode(byte* pByte, int off, int pByteLen, int& size) {
		int iOff = off;
		L9OutputStream out/* = new L9OutputStream()*/;
		while (iOff < off + pByteLen) { //pByteLen必定为2的整数倍
			byte c = pByte[iOff++];
			int len = pByte[iOff++] & 0xFF;
			for (int i = 0; i < len; i++) {
				out.writeByte(c);
			}
		}
		size = out.getOff();
		return out.getBytesN();
	}

	////////////////////////////////////////////////////压缩算法 end//////////////////////////////////////////////////////////////////////////////////////

	//////////////////////////////////////////有关字节数组的一些操作//////////////////////////////////////////////////////////////////////////////////
	/**
	 *在字节数组的off偏移处增加size大小的空间,如果arr为空，则返回off+size大小的空间
	 * 如果off大于数组arr的长度则返回off+size大小的空间,前面的数据为arr的数据
	 * @param arr byte[]
	 * @param size int
	 * @param off int
	 * @return byte[]
	 */
	static byte* addBytes(byte* arr, int arrLen, int off, int size) {
		if (arr == NULL) {
			return new byte[off + size];
		}
		byte* tmp_arr = NULL;
		if (arrLen <= off) {
			tmp_arr = new byte[off + size];
			System_arraycopy(arr, 0, tmp_arr, 0, arrLen);
		} else {
			tmp_arr = new byte[arrLen + size];
			System_arraycopy(arr, 0, tmp_arr, 0, off);
			System_arraycopy(arr, off, tmp_arr, off + size, arrLen - off);
		}
		if (arr != NULL) {
			delete[] arr;
			arr = NULL;
		}
		return tmp_arr;
	}

	/**
	 * 在字节数组的末尾新增size大小的空间,如果arr为空则返回size大小的空间
	 * @param arr byte[]
	 * @param step int
	 * @return byte[]
	 */
	static byte* addBytes(byte* arr, int arrLen, int size) {
		if (arr == NULL) {
			return new byte[size];
		}
		byte* tmp_arr = new byte[arrLen + size];
		System_arraycopy(arr, 0, tmp_arr, 0, arrLen);

		if (arr != NULL) {
			delete[] arr;
			arr = NULL;
		}
		return tmp_arr;
	}

	/**
	 * 在数组arr的off偏移处截取大小为size的字节数组，如果off+size大于arr数组的长度，则截图从off到arr末尾的字节
	 * @param arr byte[]
	 * @param size int
	 * @return byte[]
	 */
	static byte* trimBytes(byte* arr, int arrLen, int off, int size) {
		if (arr == NULL || off >= arrLen) {
			return NULL;
		}
		byte* tmp_arr = NULL;
		if (off + size >= arrLen) {
			tmp_arr = new byte[arrLen - off];
			System_arraycopy(arr, off, tmp_arr, 0, arrLen - off);
			return arr;
		} else {
			tmp_arr = new byte[size];
			System_arraycopy(arr, off, tmp_arr, 0, size);
		}
		if (arr != NULL) {
			delete[] arr;
			arr = NULL;
		}
		return tmp_arr;
	}

	/**
	 * 合并两个字节数组，返回一个新数组
	 * @param A byte[]
	 * @param B byte[]
	 * @return byte[]
	 */
	static byte* mergeBytes(byte* A, int ALen, byte* B, int BLen) {
		byte* rs = null;
		if (A == NULL) {
			rs = new byte[BLen];
			System_arraycopy(B, 0, rs, 0, BLen);
			return rs;
		}
		if (B == NULL) {
			rs = new byte[ALen];
			System_arraycopy(A, 0, rs, 0, ALen);
			return rs;
		}
		rs = new byte[ALen + BLen];
		System_arraycopy(A, 0, rs, 0, ALen);
		System_arraycopy(B, 0, rs, ALen, BLen);
		return rs;
	}

	/**
	 * 将字节数组按照所给出的大小进行分割,返回分割后的二维字节数组
	 * @param rs byte[]
	 * @param size int
	 * @return byte[][]
	 */
	static vector<byte*> splitBytesN(byte* rs, int off, int len, int size) {
		vector<byte*> vRs;
		if (len > size) {
			int steps = len / size;
			int lastSize = 0;
			if (len % size != 0) {
				lastSize = len - size * steps;
				steps++;
			}
			for (int i = 0; i < steps - 1; i++) {
				byte* p = new byte[size];
				System_arraycopy(rs, size * i, p, 0, size);
				vRs.push_back(p);
			}
			byte* p = new byte[lastSize];
			System_arraycopy(rs, size * (steps - 1), p, 0, lastSize);
			vRs.push_back(p);
		} else {
			byte* p = new byte[len];
			vRs.push_back(p);
		}
		return vRs;
	}

	/**
	 * 根据ID在数组中查找索引
	 * @param arrID int[]
	 * @param ID int
	 * @return int
	 */
	static int getIndexByID(int* arrID, int arrIDLen, int ID) {
		for (int i = 0; arrID != NULL && i < arrIDLen; i++) {
			if (arrID[i] == ID) {
				return i;
			}
		}
		return -1;
	}
	/**
	 * 在int数组中查找ID值，范围找到的索引，否则返回-1
	 *@param vector<int> arrID
	 *@param int ID
	 */
	static int getIndexByID(vector<int> arrID, int ID) {
		for (int i = 0; i < arrID.size(); i++) {
			if (arrID[i] == ID) {
				return i;
			}
		}
		return -1;
	}
	/**
	 * 抛出并捕获异常，显示堆栈信息，便于调试程序
	 * @param msg String

	 static void throwException(string msg) {
	 try {
	 System.out.println("error:" + msg);
	 throw new Exception(msg);
	 } catch (Exception ex) {
	 ex.printStackTrace();
	 }
	 }
	 */
	/**
	 * 显示友好的异常信息并显示堆栈信息
	 * @param ex Exception
	 * @param msg String

	 static void throwException(Exception ex, string msg) {
	 AppLog("error:" + msg);
	 ex.printStackTrace();
	 }
	 */
	/**
	 * 用某个值填充数组
	 * @param intArray int[]
	 * @param val int
	 * @return int[]
	 */
	static int* fillArray(int* intArray, int arrLen, int val) {
		for (int i = 0; intArray != NULL && i < arrLen; i++) {
			intArray[i] = val;
		}
		return intArray;
	}

	/**
	 * 随机打乱一个数组
	 * @param intArray int[]
	 * @return int[]
	 */
	static int* rndArray(int* intArray, int arrLen) {
		for (int i = 0; intArray != NULL && i < arrLen; i++) {
			int index1 = getRandValue(0, arrLen);
			int index2 = getDiffRandValue(index1, 0, arrLen);

			int tmp = intArray[index1];
			intArray[index1] = intArray[index2];
			intArray[index2] = tmp;
		}
		return intArray;
	}

	/**
	 * 返回整型数组中最小值的索引,如果arr为null，或者长度为0则返回-1
	 * @param arr int[]
	 * @return int
	 */
	static int getMinIndex(int* arr, int arrLen) {
		if (arr == NULL || arrLen == 0) {
			return -1;
		}
		if (arrLen == 1) {
			return 0;
		}

		int min = arr[0];
		int min_Index = 0;
		for (int i = 1; i < arrLen; i++) {
			if (arr[i] < min) {
				min = arr[i];
				min_Index = i;
			}
		}
		return min_Index;
	}

	/**
	 * 返回整型数组中最小的值
	 * @param arr int[]
	 * @return int
	 */
	static int getMinValue(int* arr, int arrLen) {
		return arr[getMinIndex(arr, arrLen)];
	}
	/**
	 * 判断字符串的某一子串是否为十进制数
	 *@param int off
	 *@param int len
	 */
	static bool isNum(String str, int off, int len) {
		str.ToLower(str);
		int strLen = str.GetLength();
		for (int i = 0; i < len && i + off < strLen; i++) {
			byte c = str[off + i];
			if (!(c == '0' || c == '1' || c == '2' || c == '3' || c == '4' || c
					== '5' || c == '6' || c == '7' || c == '8' || c == '9')) {
				return false;
			}
		}
		return true;
	}
	/**
	 * 判断字符串的某一子串是否为十六进制数
	 *@param int off
	 *@param int len
	 */
	static bool isNum16(String str, int off, int len) {
		str.ToLower(str);
		int strLen = str.GetLength();
		for (int i = 0; i < len && i + off < strLen; i++) {
			byte c = str[off + i];
			if (!(c == '0' || c == '1' || c == '2' || c == '3' || c == '4' || c
					== '5' || c == '6' || c == '7' || c == '8' || c == '9' || c
					== 'a' || c == 'b' || c == 'c' || c == 'd' || c == 'e' || c
					== 'f')) {
				return false;
			}
		}
		return true;
	}
	/**
	 * 将字符串转换为整形[2-16]进制,没有比如像0x表示16进制的前缀,默认为十进制
	 *@param String intStr
	 *@param int radix=10
	 */
	static int StrToInt(String intStr, int radix = 10) {
		intStr.ToLower(intStr);
		int rs = 0;
		for (int i = 0; i < intStr.GetLength(); i++) {
			byte c = intStr[i];
			int base = 0;
			if (c == 'a' || c == 'b' || c == 'c' || c == 'd' || c == 'e' || c
					== 'f') {
				base = c - 'a';
			} else {
				base = c - '0';
			}
			rs += (base
					* ((int) (Math::Pow(radix, intStr.GetLength() - 1 - i))));
		}
		return rs;
	}

	static byte* getFileBin(const char* sFile, int& nSize) {
		ifstream is(sFile, ios::binary);
		// get length of file:
		is.seekg(0, ios::end);
		nSize = is.tellg();
		is.seekg(0, ios::beg);
		byte* pFile = new byte[nSize];
		is.read((char*) pFile, nSize);
		is.close();
		return pFile;
	}
	static void wirteFileBin(const char* sFile, byte*buf) {
		ofstream out(sFile, ios::binary);
		char* pBuf = (char*) buf;
		out.write(pBuf, strlen(pBuf));
		out.close();
	}
	/**
	 * 将bada中的字符串转换为c风格的字符串
	 *@param String sBadaStr
	 */
	static byte* getCStringN(String sBadaStr) {
		Osp::Text::AsciiEncoding ascii;
		int byteCount = 0;
		ByteBuffer* pBuffer = ascii.GetBytesN(sBadaStr);
		byteCount = pBuffer->GetCapacity();
		byte* chPtrBuf = new byte[byteCount + 1];
		pBuffer->GetArray((byte*) chPtrBuf, 0, byteCount);
		if (pBuffer != null) {
			delete pBuffer;
		}
		return chPtrBuf;
	}
	/**
	 * 返回sFind字符串在Str字符串中首次出现的位置,如果不存在则返回-1
	 */
	static int indexOf(const String& Str, const String& sFind) {
		int index = -1;
		if (Str.GetLength() > 0) {//排除为空的情况
			Str.IndexOf(sFind, 0, index);
		}
		return index;
	}
	/**
	 * 返回ch字符在Str字符串中首次出现的位置,如果不存在则返回-1
	 */
	static int indexOf(const String& Str, mchar ch) {
		//Bada中String的IndexOf函数无法查找中文字符串的第一个字符,所以这里将ch转换为字符串以避开这个bug
		return indexOf(Str, String(ch));
	}
};
}
;

#endif /* L9UTIL_H_ */
